#pragma once
#include <string>
#include <cstring>
#include "Util.hpp"
#include <jsoncpp/json/json.h>
#define JSON
namespace yui
{

#define SEP " "
#define SEP_LEN strlen(SEP)

#define HEAD_SEP "\r\n"
#define HEAD_SEP_LEN strlen(HEAD_SEP)
#define BUFF_SIZE 1024

    // 添加报头
    void AddHeader(std::string &str)
    {
        // 先计算出长度
        size_t len = str.size();
        std::string strlen = Util::IntToStr(len);
        // 再拼接
        str = strlen + HEAD_SEP + str;
    }

    // 移除报头
    void RemoveHeader(std::string &str, size_t len)
    {
        str = str.substr(str.size() - len);
    }

    // 读取数据
    int ReadPackage(int sock, std::string &inBuff, std::string *package)
    {
        char buff[BUFF_SIZE];
        ssize_t n = recv(sock, buff, sizeof(buff) - 1, 0);
        if (n < 0)
            return -1;
        else if (n == 0)
            return 0;

        buff[n] = 0;
        inBuff += buff;
        // 判断inBuff中是否存在完整的数据包（报头\r\n有效载荷）
        int pos = inBuff.find(HEAD_SEP);
        if (pos == std::string::npos)
        {
            return -1;
        }
        std::string strLen = inBuff.substr(0, pos);
        int packLen = strLen.size() + HEAD_SEP_LEN + Util::StrToInt(strLen);
        if (inBuff.size() < packLen)
        {
            return -1;
        }
        *package = inBuff.substr(0, packLen);
        inBuff.erase(0, packLen);
        return Util::StrToInt(strLen);
    }

    class Request
    {
    public:
        Request(int x = 0, int y = 0, char op = '+')
            : x_(x), y_(y), op_(op)
        {
        }
        ~Request()
        {
        }
        // 序列化
        bool Serialization(std::string *outStr)
        {
            *outStr = ""; // 清空
#ifndef JSON
            std::string left = Util::IntToStr(x_);
            std::string right = Util::IntToStr(y_);
            *outStr = left + SEP + op_ + SEP + right;
#else
            // 使用Json
            Json::Value root;
            root["x"] = x_;
            root["op"] = op_;
            root["y"] = y_;
            Json::FastWriter writer;
            *outStr = writer.write(root);
#endif
            LOG(DEBUG, "serialzation success");
            return true;
        }
        // 反序列化
        bool Deserialization(const std::string &inStr)
        {
#ifndef JSON
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            // 协议规定：只允许存在两个操作符
            if (result.size() != 3)
            {
                return false;
            }
            // 规定：运算符只能为一个字符
            if (result[1].size() != 1)
                return false;
            x_ = Util::StrToInt(result[0]);
            y_ = Util::StrToInt(result[2]);
            op_ = result[1][0];
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr, root);

            x_ = root["x"].asInt();
            op_ = root["op"].asInt();
            y_ = root["y"].asInt();
#endif
            return true;
        }

    public:
        int x_;
        int y_;
        char op_;
    };
    class Reaponse
    {
    public:
        Reaponse(int result = 0, int code = 0)
            : result_(result), code_(code)
        {
        }
        ~Reaponse()
        {
        }
        // 序列化
        bool Serialization(std::string *outStr)
        {
#ifndef JSON
            *outStr = "";
            std::string left = Util::IntToStr(result_);
            std::string right = Util::IntToStr(code_);
            *outStr = left + SEP + right;
#else
            Json::Value root;
            root["result"] = result_;
            root["code_"] = code_;
            Json::FastWriter writer;
            *outStr = writer.write(root);
#endif
            LOG(DEBUG, "serialzation success");
            return true;
        }
        // 反序列化
        bool Deserialization(const std::string &inStr)
        {
#ifndef JSON
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if (result.size() != 2)
            {
                return false;
            }
            result_ = Util::StrToInt(result[0]);
            code_ = Util::StrToInt(result[1]);
#else 
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr,root);
            result_ = root["result"].asInt();
            code_ = root["code"].asInt();
#endif
            return true;
        }

    public:
        int result_; // 结果
        int code_;   // 错误码
    };
}